package com.jiepos.mpos.pay.quickpay.service.xk77pay;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.httpclient.NameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.alibaba.fastjson.JSON;
import com.jiepos.mpos.common.constant.SystemConstant;
import com.jiepos.mpos.core.util.DateUtil;
import com.jiepos.mpos.core.util.GlobalUtils;
import com.jiepos.mpos.core.util.HttpUtil;
import com.jiepos.mpos.core.util.MathUtils;
import com.jiepos.mpos.core.util.StringUtils;
import com.jiepos.mpos.pay.CommonService;
import com.jiepos.mpos.pay.quickpay.service.AtrPayService;
import com.jiepos.mpos.pay.quickpay.service.IQuickPayService;



/**
* 标题:
* 模块:欣客支付服务类
* 描 述: <描述>
* 版权: Copyright (c) 2017 江苏杰博实信息技术有限公司
* @author 杨剑武
* @version 1.0
* @since 2018年1月26日
* @history（历次修订内容、修订人、修订时间等）
*/
@Service("77PAYH5_TERM")
public class XinKePayService extends AtrPayService implements IQuickPayService {
	private static final Logger _log = LoggerFactory.getLogger(XinKePayService.class);
	/**
	 * 接口: <模块>
	 * 描 述: <描述>
	 * @param channelMchntCd
	 * @param orderNo
	 * @param orderAmt
	 * @param mobile
	 * @param certNo
	 * @param userName
	 * @param cardNo
	 * @param remark
	 * @param dataMap
	 * @return
	 * @since 2018年1月26日
	*/
		
	@Override
	public Map payOrder(String channelMchntCd, String orderNo, String orderAmt, String mobile, String certNo,
			String userName, String cardNo, String remark, Map dataMap) {
		Map<String, String> respMap = null;
		try {
			String payUrl = GlobalUtils.getPayConfProperty("xinke.pay.url"); // 消费测试接口地址
			String[] keys = { "gateId", "orderNo", "cardNo", "currencyCode", "phone", "name", "idNumber", "transAmt",
					"merId", "instCode", "frontUrl", "backUrl" };
			String[] params = { GlobalUtils.getPayConfProperty("xinke.pay.gateId"),
					String.valueOf(dataMap.get("loc_trace_no")), String.valueOf(dataMap.get("act_out_no")),
					GlobalUtils.getPayConfProperty("xinke.pay.currencyCode"), String.valueOf(dataMap.get("phone")),
					String.valueOf(dataMap.get("real_name")), String.valueOf(dataMap.get("certificate_no")),
					CommonService.subString(String
							.valueOf(MathUtils.mul(Double.valueOf(String.valueOf(dataMap.get("trans_at"))), 100))),
					String.valueOf(dataMap.get("trf_mchnt_cd")), GlobalUtils.getPayConfProperty("xinke.pay.instCode"),
					dataMap.get("payUrl") + GlobalUtils.getPayConfProperty("xinke.pay.returnUrl"),
					dataMap.get("payUrl") + GlobalUtils.getPayConfProperty("xinke.pay.notifyUrl") };
			StringBuilder builder = new StringBuilder();
			for (int i = 0; i < keys.length; i++) {
				builder.append(keys[i]);
				builder.append("=");
				builder.append(params[i]);
				builder.append("&");
			}
			builder.deleteCharAt(builder.length() - 1);
			String sign = PayHelper
					.getMD5Str(builder.toString() + GlobalUtils.getPayConfProperty("xinke.pay.sigKey"));
			builder.append("&sign");
			builder.append("=");
			builder.append(sign);
			_log.info("[{}]交易[{}]渠道,请求数据为:[{}]", dataMap.get("loc_trace_no"), dataMap.get("channel_No"),
					builder.toString());
			String requestData = PayHelper.getEncodeStr(builder.toString());
			requestData = PayHelper.encode(requestData.getBytes());
			requestData = PayHelper.filter(requestData);
			requestData = URLEncoder.encode(requestData, SystemConstant.UTF_ENCODING);
			NameValuePair[] httpsData = new NameValuePair[1];
			httpsData[0] = new NameValuePair("sText", requestData);
			String result = HttpUtil.getHttpClientData(payUrl, httpsData);
			_log.info("[{}]交易[{}]渠道,响应数据为:[{}]", dataMap.get("loc_trace_no"), dataMap.get("channel_No"), result);
			if (!StringUtils.isEmpty(result)) {
				respMap = CommonService.parseJsonToMap(result);
				respMap.put("loc_trace_no", String.valueOf(dataMap.get("loc_trace_no")));
				respMap.put("rspcode", respMap.get("code"));
				respMap.put("rspmsg", respMap.get("message"));
				if (!StringUtils.isEmpty(respMap.get("url"))) {
					respMap.put("sourceData", htmlData(respMap.get("url")));
				}
				return getStandardData(respMap);
			}
			return null;
		} catch (Exception e) {
			_log.error("欣客支付渠道发生异常", e);
			return null;
		}
	}
	
	/**
	 * 接口: <模块>
	 * 描 述: <描述>
	 * @param paramMap
	 * @return
	 * @since 2018年1月26日
	*/
		
	@Override
	public boolean noticeOrder(Map<String, String> paramMap) {
		_log.info("欣客异步通知原始数据map=[{}]",paramMap);
		Map<String, String> standardMap = noticeStandard(paramMap);
		boolean flag = false;
		try {
			flag = noticeService.noticeUpdate(standardMap);
		} catch (Exception e) {
			flag = false;
			_log.error("欣客异步通知更新发生异常", e);
		}
		return flag;
	}
	
	/**
	 * 回调标准化
	 * @param payResMap
	 * @return
	 */
	private Map<String, String> noticeStandard(Map<String, String> payResMap) {
		
		Map<String, String> standardDataMap = new HashMap<String, String>();
		standardDataMap.put("trf_mchnt_cd", "");// 商户编号（渠道）
		standardDataMap.put("trf_term_id", "");// 终端编号（渠道）				
		standardDataMap.put("complete_dt", String.valueOf(payResMap.get("transDate")));// 订单完成日期（渠道）
		standardDataMap.put("complete_ts", String.valueOf(payResMap.get("transTime")));// 订单完成时间（渠道）
		standardDataMap.put("custom_no", "");// 商户编号（支付系统）
		standardDataMap.put("term_id", "");// 终端编号（支付系统）
		standardDataMap.put("trf_trace_no", payResMap.get("transSeq"));// 渠道方流水号（渠道）
		standardDataMap.put("loc_trace_no", payResMap.get("orderNo"));// 本地流水号（支付系统）
		String rspcode = CommonService.encapRespCode(payResMap.get("transStatus"), null);
		String rspmsg = SystemConstant.RSPCODE_SUCCESS.equals(rspcode) ? SystemConstant.RSPCODE_SUCCESS_PAY
				: String.valueOf(noticeService.getRspCodeListMap().get(rspcode));
		standardDataMap.put("trs_stat",rspcode);// 交易状态
		
		standardDataMap.put("stlst", "0");// 清算状态（出款状态）
		standardDataMap.put("stl_dt", "");// 清算日期			
		standardDataMap.put("midfee", "");// 商户手续费		
		standardDataMap.put("costfee", "");// 成本手续费	
		standardDataMap.put("stl_amt", "");// 结算金额
		standardDataMap.put("trans_at", String.valueOf(payResMap.get("transAmt")));// 交易金额		
		standardDataMap.put("rspcode", rspcode);// 返回码
		standardDataMap.put("rspmsg", rspmsg);// 返回信息描述
		standardDataMap.put("pay_dt", "");// 出款日期
		standardDataMap.put("pay_ts", "");// 出款时间
		_log.info("欣客标准化异步通知报文map=[{}]", standardDataMap);
		return standardDataMap;
	}

	/**
	 * 接口: <模块>
	 * 描 述: <描述>
	 * @param queryMap
	 * @return
	 * @since 2018年1月26日
	*/
		
	@Override
	public Map<String, String> queryChannelOrder(Map<String, String> queryMap) {
		
		try {
			Map<String, Object> transMap=transQuery(queryMap);
			Map<String, String> standardMap=tradeStandard(transMap,queryMap.get("loc_trace_no"));
			if(SystemConstant.RSPCODE_SUCCESS.equals(standardMap.get("rspcode"))){
				Map<String, Object> tradeMap = withdrawQuery(standardMap);
				return withdrawStandard(tradeMap,standardMap);				
			}else{
				return standardMap;
			}			
			
		}catch (Exception e) {
			_log.error("欣客主动查询请求发生异常", e);
			return new HashMap<String, String>();
		}		
		
	}
	
	/**
	 * 支付查询标准化报文
	 * @param tradeReceiveMap
	 * @param loc_trace_no
	 * @return
	 */
	private Map<String, String> tradeStandard(Map<String, Object> tradeReceiveMap,String loc_trace_no){
		Map<String, String> respMap = new HashMap<String, String>();
		Map<String, String> infoMap = appLogTransJnlsPayService.getTranInfo(loc_trace_no);
		respMap.put("trf_mchnt_cd", infoMap.get("trf_mchnt_cd"));// 商户编号（渠道）
		respMap.put("trf_term_id", infoMap.get("trf_term_id"));// 终端编号（渠道）
		respMap.put("custom_no", infoMap.get("custom_no"));// 客户编号（支付系统）
		respMap.put("loc_trace_no", loc_trace_no);// 本地流水号（支付系统)
		respMap.put("stlst", infoMap.get("stlst"));// 清算状态(待定)
		respMap.put("trans_at", String.valueOf(MathUtils.mul(Double.valueOf(infoMap.get("trans_at")), 100)));// 交易金额(数据库查询)
		respMap.put("midfee", String.valueOf(MathUtils.mul(Double.valueOf(infoMap.get("midfee")), 100)));// 商户手续费
		respMap.put("complete_dt", infoMap.get("complete_dt"));// 订单完成日期（渠道）
		respMap.put("complete_ts", infoMap.get("complete_ts"));// 订单完成时间（渠道）
		String rspcode = infoMap.get("rspcode");// 返回码
		String rspmsg = infoMap.get("rspmsg");// 交易返回信息
		if (tradeReceiveMap!=null&&!tradeReceiveMap.isEmpty()) {
			rspcode=CommonService.encapResultCode(String.valueOf(tradeReceiveMap.get("code")));			
			if(SystemConstant.RSPCODE_SUCCESS.equals(rspcode)){												
				String complete_dt=StringUtils.isBlank(String.valueOf(tradeReceiveMap.get("payTime")))?"":DateUtil.toString(DateUtil.StrToDate(String.valueOf(tradeReceiveMap.get("payTime"))),"yyyyMMdd");
				String complete_ts=StringUtils.isBlank(String.valueOf(tradeReceiveMap.get("payTime")))?"":DateUtil.toString(DateUtil.StrToDate(String.valueOf(tradeReceiveMap.get("payTime"))),"HHmmss");
				respMap.put("complete_dt", complete_dt);// 订单完成日期（渠道）
				respMap.put("complete_ts", complete_ts);// 订单完成时间（渠道）
				respMap.put("term_id", "");// 终端编号（支付系统）
				respMap.put("trf_trace_no", String.valueOf(tradeReceiveMap.get("transSeq")));// 渠道方流水号（渠道）
				respMap.put("trs_stat", CommonService.encapRespCode(String.valueOf(tradeReceiveMap.get("status")), null));// 交易状态
				respMap.put("stl_dt", "");// 清算日期				
				respMap.put("stl_amt", "");// 结算金额
				respMap.put("stlst", "0");// 清算状态				
				respMap.put("midfee", "");// 商户手续费
				respMap.put("rcvfee", "");// 接收方手续费
				respMap.put("costfee", "");// 成本手续费
				respMap.put("pay_dt", "");// 出款日期
				respMap.put("pay_ts", "");// 出款时间
				rspcode = CommonService.encapRespCode(String.valueOf(tradeReceiveMap.get("status")), null);
				rspmsg = SystemConstant.RSPCODE_SUCCESS.equals(rspcode) ? SystemConstant.RSPCODE_SUCCESS_PAY
						: String.valueOf(noticeService.getRspCodeListMap().get(rspcode));	
			}else{
				respMap.put("errorCode", String.valueOf(tradeReceiveMap.get("code")));// 渠道返回码
				respMap.put("msg", String.valueOf(tradeReceiveMap.get("message")));// 渠道返回信息
				rspcode=CommonService.encapRespCode(rspcode,null);
				rspmsg = StringUtils.isBlank( String.valueOf(tradeReceiveMap.get("message"))) ? 
						String.valueOf(noticeService.getRspCodeListMap().get(rspcode)): String.valueOf(tradeReceiveMap.get("message"));
			}
		}	
		
		respMap.put("rspcode", rspcode);// 返回码
		respMap.put("rspmsg", rspmsg);// 交易返回信息
		_log.info("欣客支付主动查询标准报文map=[{}]", respMap);
		return respMap;
	}
	
	/**
	 * 结算查询标准化
	 * @param payResMap
	 * @param standardMap
	 * @return
	 */
	private Map<String, String> withdrawStandard(Map<String, Object> payResMap,Map<String, String> standardMap){								
		if (payResMap!=null&&!payResMap.isEmpty()) {
			String rspcode=CommonService.encapResultCode(String.valueOf(payResMap.get("code")));			
			if(SystemConstant.RSPCODE_SUCCESS.equals(rspcode)){		
				String pay_dt=StringUtils.isBlank(String.valueOf(payResMap.get("handleTime")))?"":DateUtil.toString(DateUtil.StrToDate(String.valueOf(payResMap.get("handleTime"))),"yyyyMMdd");
				String pay_ts=StringUtils.isBlank(String.valueOf(payResMap.get("handleTime")))?"":DateUtil.toString(DateUtil.StrToDate(String.valueOf(payResMap.get("handleTime"))),"HHmmss");								
				standardMap.put("trf_stl_trace_no", String.valueOf(payResMap.get("batchNo")));// 渠道清算流水号（支付系统）				
				standardMap.put("stl_dt", pay_dt);// 清算日期				
				standardMap.put("stl_amt", StringUtils.isBlank(String.valueOf(payResMap.get("actualAmount")))?"0":String.valueOf(payResMap.get("actualAmount")));// 结算金额
				String stlst=CommonService.encapSettleRespCode(String.valueOf(payResMap.get("transferStatus")));
				standardMap.put("stlst", stlst);// 清算状态								
				standardMap.put("pay_dt", pay_dt);// 出款日期
				standardMap.put("pay_ts", pay_ts);// 出款时间									
			}
		}					
		_log.info("欣客结算主动查询标准报文map=[{}]", standardMap);
		return standardMap;
	}
	
	/**
	 * 支付查询
	 * @param queryMap
	 * @return
	 */
	private Map<String, Object> transQuery(Map<String, String> queryMap) {
		
		Map<String, Object> repMap=new HashMap<String, Object>();
		String time=appLogTransJnlsPayService.getCloseOrderTime();
		String queryTransUrl = GlobalUtils.getPayConfProperty("xinke.transquery.url");       //http://27.115.99.214:9974/outcome/query-trans/transQuery
	    String merId = String.valueOf(queryMap.get("trf_mchnt_cd"));                                                                              //欣客平台分配商户号
	    String instId = GlobalUtils.getPayConfProperty("xinke.pay.instCode");                                                                              //欣客平台分配机构号
	    String pageNo = "1";                                                                   //1、订单列表第几页，必须是正整数 2、每页显示20条数据
	    String orderId = String.valueOf(queryMap.get("loc_trace_no"));                                                                  //交易流水号
	    String payTimeBegin = DateUtil.toString(new Date(DateUtil.toDate(String.valueOf(queryMap.get("loc_dt"))+String.valueOf(queryMap.get("loc_ts")),"yyyyMMddHHmmss").getTime() - (long)5 * 60 * 1000));                                                                    //支付开始时间
	    String payTimeEnd = DateUtil.toString(new Date(DateUtil.toDate(String.valueOf(queryMap.get("loc_dt"))+String.valueOf(queryMap.get("loc_ts")),"yyyyMMddHHmmss").getTime() + (long)Integer.parseInt(time) * 60 * 1000));                                                                      //支付结束时间
	    String sigKey = GlobalUtils.getPayConfProperty("xinke.pay.query.sigKey");                                              //秘钥Key(生产)
	    String[] keys = {"merId", "instId", "pageNo", "orderId", "payTimeBegin", "payTimeEnd"};
        String[] params = {merId, instId, pageNo, orderId, payTimeBegin, payTimeEnd};
        try{
        	_log.info("欣客支付主动查询请求数据:merId:[{}],instId:[{}],orderId:[{}],payTimeBegin:[{}],payTimeEnd:[{}]",merId
        			,instId,orderId,payTimeBegin,payTimeEnd);
        	String result = PayHelper.build(keys, params, queryTransUrl, sigKey);
            // 打印最终提交的form表单
        	_log.info("欣客支付主动查询结果：" + result);
        	if(!StringUtils.isBlank(result)){       		
        		Map<String, Object> resultMap=JSON.parseObject(result);
        		List<Map> list=JSON.parseArray(String.valueOf(resultMap.get("translist")),Map.class);
        		for(Map map:list){
        			if(String.valueOf(queryMap.get("loc_trace_no")).equals(map.get("orderNo"))){               			
        				repMap=map;
        				repMap.put("code", String.valueOf(resultMap.get("code")));
                		repMap.put("message", String.valueOf(resultMap.get("message")));
        			}               		
        		}       		
        	}
        }catch(Exception e){
        	_log.error("欣客支付主动查询发生异常",e);
        }
        
        return repMap;
    }
	/**
	 * 结算查询
	 * @param queryMap
	 * @return
	 */
	private Map<String, Object> withdrawQuery(Map<String, String> queryMap) {
		
		Map<String, Object> repMap=new HashMap<String, Object>();
		String time=appLogTransJnlsPayService.getCloseOrderTime();
		String queryAccountUrl = GlobalUtils.getPayConfProperty("xinke.withdrawquery.url");       //生产
	    String merId = String.valueOf(queryMap.get("trf_mchnt_cd"));                                                                              //欣客平台分配商户号
	    String instId = GlobalUtils.getPayConfProperty("xinke.pay.instCode");                                                                              //欣客平台分配机构号
	    String pageNo = "1";                                                                   //1、订单列表第几页，必须是正整数 2、每页显示20条数据
	    String requestDateStart = DateUtil.toString(new Date(DateUtil.toDate(String.valueOf(queryMap.get("complete_dt"))+String.valueOf(queryMap.get("complete_ts")),"yyyyMMddHHmmss").getTime() - (long)5 * 60 * 1000));                                                                    //请求开始时间
	    String requestDateEnd = DateUtil.toString(new Date(DateUtil.toDate(String.valueOf(queryMap.get("complete_dt"))+String.valueOf(queryMap.get("complete_ts")),"yyyyMMddHHmmss").getTime() + (long)Integer.parseInt(time) * 60 * 1000));                                                                      //请求结算时间
	    String sigKey = GlobalUtils.getPayConfProperty("xinke.pay.query.sigKey");                                              //秘钥Key(生产)
		String[] keys = {"merId", "instId","pageNo", "requestDateStart", "requestDateEnd"};
        String[] params = {merId, instId,pageNo, requestDateStart, requestDateEnd};
        try{
        	_log.info("欣客结算主动查询请求数据:merId:[{}],instId:[{}],loc_trace_no:[{}],requestDateStart:[{}],requestDateEnd:[{}]",merId
        			,instId,String.valueOf(queryMap.get("loc_trace_no")),requestDateStart,requestDateEnd);
        	String result = PayHelper.build(keys, params, queryAccountUrl, sigKey);
            // 打印最终提交的form表单
        	_log.info("欣客结算主动查询结果：" + result);
        	if(!StringUtils.isBlank(result)){        		
        		Map<String, Object> resultMap=JSON.parseObject(result);
        		List<Map> list=JSON.parseArray(String.valueOf(resultMap.get("translist")),Map.class);
        		for(Map map:list){
        			if(String.valueOf(queryMap.get("loc_trace_no")).equals(map.get("orderNo"))){               			
        				repMap=map;
        				repMap.put("code", String.valueOf(resultMap.get("code")));
                		repMap.put("message", String.valueOf(resultMap.get("message")));
        			}               		
        		}        		
        	}
        }catch(Exception e){
        	_log.error("欣客结算主动查询发生异常",e);
        }
        
        return repMap;
    }
	
	

	/**
	 * 接口: <模块>
	 * 描 述: <描述>
	 * @param reqMap
	 * @return
	 * @since 2018年1月26日
	*/
		
	@Override
	public Map<String, String> verifyCode(Map<String, String> reqMap) {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * 接口: <模块>
	 * 描 述: <描述>
	 * @param queryMap
	 * @return
	 * @since 2018年1月26日
	*/
		
	@Override
	public Map<String, String> queryChannelStlResult(Map<String, String> queryMap) {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * 接口: <模块>
	 * 描 述: <描述>
	 * @param reqMap
	 * @return
	 * @throws Exception
	 * @since 2018年1月26日
	*/
		
	@Override
	public Map<String, String> getStandardData(Map<String, String> reqMap) throws Exception {
		Map<String, String> respMap = new HashMap<String, String>();
		Assert.notNull(reqMap.get("loc_trace_no"));
		Map<String, String> infoMap = appLogTransJnlsPayService.getTranInfo(reqMap.get("loc_trace_no"));
		log.info("欣客支付响应报文为:[{}],[{}]交易对应的查询数据为:[{}]",reqMap,reqMap.get("loc_trace_no"),infoMap);
		Map<String, Object> traceTime = mainBusinessService.getSystemTime();
		respMap.put("loc_dt", String.valueOf(traceTime.get("loc_dt")));//交易日期
		respMap.put("loc_ts", String.valueOf(traceTime.get("loc_ts")));//交易日期
		respMap.put("trf_mchnt_cd", infoMap.get("trf_mchnt_cd"));// 商户编号（渠道）
		respMap.put("trf_term_id", infoMap.get("trf_term_id"));// 终端编号（渠道）
		respMap.put("complete_dt", reqMap.get("complete_dt"));// 订单完成日期（渠道）
		respMap.put("complete_ts", reqMap.get("complete_ts"));// 订单完成时间
		respMap.put("custom_no", infoMap.get("custom_no"));// 客户编号（支付系统）
		respMap.put("term_id", reqMap.get("term_id"));// 本地流水号（支付系统)
		respMap.put("trf_trace_no", reqMap.get("trf_trace_no"));// 渠道方流水号（渠道）
		respMap.put("loc_trace_no", reqMap.get("loc_trace_no"));
		respMap.put("trs_stat", reqMap.get("trs_stat"));// 交易状态
		respMap.put("stlst", infoMap.get("stlst"));// 清算状态
		respMap.put("midfee", infoMap.get("midfee"));// 商户手续费
		respMap.put("stl_amt", reqMap.get("stl_amt"));// 结算金额
		respMap.put("rspcode", reqMap.get("rspcode"));// 返回码
		respMap.put("rspmsg", reqMap.get("rspmsg"));// 交易返回信息
		respMap.put("action", reqMap.get("action_url"));// 银联跳转页面
		respMap.put("action_method", reqMap.get("action_method"));// 银联跳转页面
		respMap.put("data", reqMap.get("data"));// 支付数据
		respMap.put("url", reqMap.get("url"));// 未使用
		respMap.put("sourceData", reqMap.get("sourceData"));// 交易返回信息
		respMap.put("channel_type", SystemConstant.CHANNEL_TYPE_H5);
		log.info("欣客支付响应报文转标准化系统处理报文[{}]",respMap);
		return respMap;
	}

	private String htmlData(String url) {
		StringBuilder builder = new StringBuilder("<html><head><meta charset='utf-8'/><title></title></head><script>");
		builder.append("window.location.href = '");
		builder.append(url);
		builder.append("'</script><body><body/></html>");
		return builder.toString();
	}

	@Override
	public Map<String, String> sendVerifyCode(Map<String, String> reqMap) {
		return null;
	}
}
